#include "u8g2Port.h"
#include "softI2C.h"
#include "main.h"
#define SS1312_DEVICE_ADDRESS 0x3C
// u8g2 gpio:
// lcd reset : PA8
// lcd scl:PC6
// lcd sda:PA11
/*
typedef struct
{
    // I2C总线的引脚控制
    void (*sclIn)(void);
    void (*sclOut)(void);
    void (*sclHigh)(void);
    void (*sclLow)(void);
    void (*sdaIn)(void);
    void (*sdaOut)(void);
    void (*sdaHigh)(void);
    void (*sdaLow)(void);
    unsigned char (*sdaRead)(void);
    void (*delay)(void);
    unsigned char isErr; // 指示是否出错，出错置为1，
} SoftI2cHandler;
*/
static LL_GPIO_InitTypeDef GPIO_InitStruct;
void u8g2SclIn(void)
{
    // GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    // GPIO_InitStruct.Pin = GPIO_PIN_6;
    // GPIO_InitStruct.Pull = GPIO_NOPULL;
    // HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT;
    GPIO_InitStruct.Pin = LL_GPIO_PIN_6;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
    LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

void u8g2SclOut(void)
{
    // GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    // GPIO_InitStruct.Pin = GPIO_PIN_6;
    // GPIO_InitStruct.Pull = GPIO_NOPULL;
    // HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
    GPIO_InitStruct.Pin = LL_GPIO_PIN_6;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

void u8g2SclHigh(void)
{
    // HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);
    LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_6);
}
void u8g2SclLow(void)
{
    // HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
    LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_6);
}
void u8g2SdaIn(void)
{
    // GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    // GPIO_InitStruct.Pin = GPIO_PIN_11;
    // GPIO_InitStruct.Pull = GPIO_NOPULL;
    // HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT;
    GPIO_InitStruct.Pin = LL_GPIO_PIN_11;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
    LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

void u8g2SdaOut(void)
{
    // GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    // GPIO_InitStruct.Pin = GPIO_PIN_11;
    // GPIO_InitStruct.Pull = GPIO_NOPULL;
    // HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
    GPIO_InitStruct.Pin = LL_GPIO_PIN_11;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

void u8g2SdaHigh(void)
{
    // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_SET);
    LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_11);
}

void u8g2SdaLow(void)
{
    // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_RESET);
    LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_11);
}

unsigned char u8g2SdaRead(void)
{
    // return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11);
    return LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_11);
}

void u8g2ResetLcd(void)
{

    //reset
    LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_8);
    LL_mDelay(100);
    LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_8);
    LL_mDelay(100);
    LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_8);
}

void u8g2Delay(void)
{
    // HAL_Delay(1);
}

static SoftI2cHandler softI2cHandler = {
    .delay = u8g2Delay,
    .sclHigh = u8g2SclHigh,
    .sclIn = u8g2SclIn,
    .sclLow = u8g2SclLow,
    .sclOut = u8g2SclOut,
    .sdaHigh = u8g2SdaHigh,
    .sdaIn = u8g2SdaIn,
    .sdaLow = u8g2SdaLow,
    .sdaRead = u8g2SdaRead,
    .sdaOut = u8g2SdaOut};

uint8_t u8x8_byte_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    static uint8_t buffer[32]; /* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
    static uint8_t buf_idx;
    uint8_t *data;

    switch (msg)
    {
    case U8X8_MSG_BYTE_SEND:
        data = (uint8_t *)arg_ptr;
        while (arg_int > 0)
        {
            buffer[buf_idx++] = *data;
            data++;
            arg_int--;
        }
        break;
    case U8X8_MSG_BYTE_INIT:

        break;
    case U8X8_MSG_BYTE_SET_DC:
        break;
    case U8X8_MSG_BYTE_START_TRANSFER:
        buf_idx = 0;
        break;
    case U8X8_MSG_BYTE_END_TRANSFER:
        softI2cWriteMultData(&softI2cHandler, u8x8_GetI2CAddress(u8x8) >> 1, buffer, buf_idx);
        break;
    default:
        return 0;
    }
    return 1;
}

uint8_t u8x8_gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
    switch (msg)
    {
    case U8X8_MSG_GPIO_AND_DELAY_INIT:
        break;
    case U8X8_MSG_DELAY_MILLI:
        LL_mDelay(arg_int);
        break;
    case U8X8_MSG_GPIO_I2C_CLOCK:
        break;
    case U8X8_MSG_GPIO_I2C_DATA:
        break;
    default:
        return 0;
    }

    return 1;
}

void u8x8PortInit(void)
{
    u8g2ResetLcd();
    softI2cInit(&softI2cHandler);
}
